/*
 * note "crypto - AVB" related file
 * Copyright (C) 2023 Dramalife <dramalife@live.com>
 *
 * note is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 * Init : Sat, 03 Jun 2023 13:10:52 +0800
 * Update
 *
 */

#include <stdint.h>
#include <stdio.h>
#include <sys/stat.h>

#include "libavb/avb_sha.h"
#include "libavb/libavb.h"

int main(int argc, char** argv)
{
    FILE* f;
    struct stat statbuf;
    AvbSHA256Ctx sha256_ctx;
    const AvbAlgorithmData* algorithm;
    uint8_t* computed_hash;
    const char *file_key, *file_raw, *file_sign;
    size_t len_key = 0, len_sign = 0, len_raw = 0;
    const char *ptr_key = NULL, *ptr_sign = NULL, *ptr_raw = NULL;

    algorithm = avb_get_algorithm_data(AVB_ALGORITHM_TYPE_SHA256_RSA2048);
    avb_sha256_init(&sha256_ctx);

    file_key = argv[1];
    file_raw = argv[2];
    file_sign = argv[3];

    /* Read PublicKey*/
    stat(file_key, &statbuf);
    len_key = statbuf.st_size;
    ptr_key = malloc(len_key);
    if ((f = fopen(file_key, "rb")) == NULL) {
        printf("\n  ! Could not open %s\n\n", file_key);
        goto exit;
    }
    len_key = fread(ptr_key, 1, len_key, f);
    printf("key.len: %zu\n", len_key);
    fclose(f);

    /* Read Signature */
    stat(file_sign, &statbuf);
    len_sign = statbuf.st_size;
    ptr_sign = malloc(len_sign);
    if ((f = fopen(file_sign, "rb")) == NULL) {
        printf("\n  ! Could not open %s\n\n", file_sign);
        goto exit;
    }
    len_sign = fread(ptr_sign, 1, len_sign, f);
    printf("sign.len: %zu\n", len_sign);
    fclose(f);

    /* Read RAW */
    stat(file_raw, &statbuf);
    len_raw = statbuf.st_size;
    ptr_raw = malloc(len_raw);
    if ((f = fopen(file_raw, "rb")) == NULL) {
        printf("\n  ! Could not open %s\n\n", file_raw);
        goto exit;
    }
    len_raw = fread(ptr_raw, 1, len_raw, f);
    printf("raw.len: %zu\n", len_raw);
    fclose(f);

    /* Cac MD : RAW -> MD*/
    avb_sha256_update(
        &sha256_ctx, ptr_raw, len_raw);
    computed_hash = avb_sha256_final(&sha256_ctx);
    printf("Hash(%d):\n", AVB_SHA256_DIGEST_SIZE);
    for (int i = 0; i < AVB_SHA256_DIGEST_SIZE; i++)
        printf("%02x %s", computed_hash[i], (i + 1) % 16 ? "" : "\n");

    /* Verify : PublicKey + Signature + MD*/
    printf("sign - len: %zu \n", len_sign);
    bool ret = false;
    ret = avb_rsa_verify(
        ptr_key, len_key,
        ptr_sign, len_sign,
        computed_hash, AVB_SHA256_DIGEST_SIZE,
        algorithm->padding,
        algorithm->padding_len);
    printf("verify: %s \n", ret ? "true" : "false");

exit:
    if (ptr_key)
        free(ptr_key);
    if (ptr_raw)
        free(ptr_raw);
    if (ptr_sign)
        free(ptr_sign);
}
